package edu.luc.cs413s13.team1.monsterm.model;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import android.util.Log;

import edu.luc.cs413s13.team1.monsterm.model.cell.Cell;
import edu.luc.cs413s13.team1.monsterm.model.cell.CellWorld;
import edu.luc.cs413s13.team1.monsterm.model.common.Constants;
import edu.luc.cs413s13.team1.monsterm.model.common.LevelChangeListener;
import edu.luc.cs413s13.team1.monsterm.model.common.ModelChangeListener;
import edu.luc.cs413s13.team1.monsterm.model.monster.Actor;
import edu.luc.cs413s13.team1.monsterm.model.monster.Monster;
import edu.luc.cs413s13.team1.monsterm.model.timer.LevelTimer;
import edu.luc.cs413s13.team1.monsterm.model.timer.MonsterCreator;
import edu.luc.cs413s13.team1.monsterm.model.timer.MonstermTimer;

/**
 * The concrete model facade
 * abstracts the whole logic of the application
 *
 */
public class DefaultMonstermModel implements MonstermModel {
	private ModelChangeListener modelChangeListener;
	private CellWorld world;
    ArrayList<Actor> livingActors;
    private int score = 0;
    private int currentLevel = 1;
    private MonstermTimer levelTimer = new LevelTimer();
    private MonstermTimer monsterCreator = new MonsterCreator();
    
    public int getCurrentLevel() {
    	return currentLevel;
    }

	
	public DefaultMonstermModel(Cell[][] grid, ModelChangeListener listener) {
		setModelChangeListener(listener);
		world = new CellWorld(grid);
		livingActors = new ArrayList<Actor>();
		levelTimer.setOnTimerChangeListener(this);
		monsterCreator.setOnTimerChangeListener(this);
		levelTimer.start();
	}
	
	public CellWorld getWorld() {
		return world;
	}
	
	@Override
	public void setModelChangeListener(ModelChangeListener listener) {
		this.modelChangeListener = listener;
	}
	
	public void setLevelChangeListener(LevelChangeListener listener) {
		this.levelChangeListener = listener;
	}
	LevelChangeListener levelChangeListener;

	@Override
	public void addActor(Actor actor, int xpos, int ypos) {
		world.addActor(actor, xpos, ypos);
	}

	@Override
	public List<Actor> getLivingActors() {
		return livingActors;
	}

	@Override
	public int getScore() {
		return score;
	}

	@Override
	public void updateScore(int score) {
		this.score += score;
	}


	@Override
	public synchronized void addLivingActor(Actor actor) {
		livingActors.add(actor);
	}


	@Override
	public synchronized void removeLivingActor(Actor actor) {
		livingActors.remove(actor);
	}


	@Override
	public void onTimerChange(MonstermTimer observer) {
		Random random = new Random();
		Log.w(Constants.TAG, "Timer triggered!");
		if (observer instanceof LevelTimer) {
			currentLevel ++;
			levelChangeListener.onLevelChange(currentLevel);
			levelTimer.stop();
			levelTimer.start();
			monsterCreator.start();
		} else {
			Log.w(Constants.TAG, "Creating new monsters now!");
			Monster m = new Monster();
			if (m != null) {
				m.setStateSleepTime(200);
				m.setMoveSleepTime(1800);
				m.setMonsterStateChangeListener(this);
				int x = random.nextInt(world.getGrid().length);
				int y = random.nextInt(world.getGrid()[0].length);
				world.addActor(m, y, x);
				Log.w(Constants.TAG, "Ccurrent count: "+livingActors.size());
				livingActors.add(m);
				m.start();
			}
		}
	}


	@Override
	public void onMonsterStateChange(int stateId) {
		modelChangeListener.onMonsterStateChange(stateId);
	}


	/**
	 * Cleanly stop the model when application finishes
	 */
	@Override
	public void exitMonsterm() {
		levelTimer.stop();
		monsterCreator.stop();
		for (Actor m : livingActors) {
			m.kill();
		}
		
	}

}
